package org.redmagic.client.prototype;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.redmagic.spring.RedMagicStringValueResolver;

import com.google.common.io.Files;

public class RMConfigurationIntializer {

	private static final Log LOG = LogFactory.getLog(RMConfigurationIntializer.class);
	private static final RedMagicStringValueResolver DEFAULT_RESOLVER = new RedMagicStringValueResolver();
	
	private RMConfigurationIntializer() {
		// private constructor so it can't be instantiated
	}
	
	public static String resolveConfigurationFile(String magicConfigFileName, String... magicConfigSetupFileNames) {
		Properties wellKnownProperties = WellKnownPropertyResolver.getWellKnownProperties();
		Properties resolvedProperties = new Properties(wellKnownProperties);
		loadPropertiesFromSetupFiles(magicConfigSetupFileNames, resolvedProperties);
		return resolvedMagicConfigFileContents(magicConfigFileName, resolvedProperties);
	}

	private static void loadPropertiesFromSetupFiles(String[] magicConfigSetupFileNames, Properties resolvedProperties) {
		for (String magicConfigSetupFileName : magicConfigSetupFileNames) {
			String resolvedMagicConfigSetupFileName = resolvePlaceholders(magicConfigSetupFileName, resolvedProperties);
			resolvedProperties.putAll(loadPlaceholders(resolvedMagicConfigSetupFileName));
		}
		if (LOG.isDebugEnabled()) {
			LOG.debug("Placeholders for magic config file: " + resolvedProperties);
		}
	}

	private static String resolvePlaceholders(String magicConfigSetupFileName, Properties resolvedProperties) {
		DEFAULT_RESOLVER.setResolvedProperties(resolvedProperties);
		return DEFAULT_RESOLVER.resolveStringValue(magicConfigSetupFileName);
	}

	private static Properties loadPlaceholders(String resolvedMagicConfigSetupFileName) {
		Properties properties = new Properties();
		try {
			InputStream is = new FileInputStream(new File(resolvedMagicConfigSetupFileName));
			properties.load(is);
			is.close();
		} catch (FileNotFoundException fnfe) {
			LOG.warn("Unable to find setup file " + resolvedMagicConfigSetupFileName);
		} catch (IOException ioe) {
			LOG.warn("Unable to load properties from setup file: " + resolvedMagicConfigSetupFileName, ioe);
		}
		return properties;
	}
	
	private static String resolvedMagicConfigFileContents(String magicConfigFileName, Properties resolvedProperties) {
		String resolvedMagicConfigFileName = resolvePlaceholders(magicConfigFileName, resolvedProperties);
		try {
        	// Load the original magic config file
	        String magicConfigContents = Files.toString(new File(resolvedMagicConfigFileName), Charset.defaultCharset());
	        
	        // Resolve any placeholders in the magic config file
	        String resolvedMagicConfigContents = resolvePlaceholders(magicConfigContents, resolvedProperties);
	        
	        // Check for any remaining placeholders in the magic config file
	        Set<String> unresolvedPlaceholders = DEFAULT_RESOLVER.resolveStringValueAsync(resolvedMagicConfigContents);
	        if (!unresolvedPlaceholders.isEmpty()) {
	        	LOG.error("Unable to resolve the following placeholders: " + unresolvedPlaceholders);
	        	throw new RuntimeException("Unable to resolve the following placeholders: " + unresolvedPlaceholders);
	        }
	        
	        // Return the fully resolved magic config file
	        return resolvedMagicConfigContents;
        } catch (IOException ioe) {
        	LOG.error("Unable to prepare magic config from file: " + resolvedMagicConfigFileName, ioe);
        	throw new RuntimeException("Unable to prepare magic config from file: " + resolvedMagicConfigFileName, ioe);
        }
	}
}
